#ifndef _f239dbe3_61ae_4e54_81bc_b829a35f6e9f__ANY_H__
#define _f239dbe3_61ae_4e54_81bc_b829a35f6e9f__ANY_H__
 
/* eg:
	int i = 9;
	Any v = i;
	int val = any_cast<int>(v);
	int* j = any_cast<int>(&v);

	std::string s = "216123";
	Any ss = s;
	std::string gg = any_cast<std::string>(s);
*/
#define JELLY_WINDOWS
#ifdef JELLY_WINDOWS
	#include <iostream>
#endif // JELLY_WINDOWS

#ifdef JELLY_LINUX
#include <typeinfo>
#endif // JELLY_LINUX

namespace any
{
	template <class T>
	struct remove_pr
	{
		typedef T value_type;
	};

	template <>
	struct remove_pr<void>
	{
		typedef void value_type;
	};

	template <class T>
	struct remove_pr<T*> 
	{
		typedef T value_type;
	};

	template <class T>
	struct remove_pr<const T*> 
	{
		typedef T value_type;
	};

	template <class T>
	struct remove_pr<T&> 
	{
		typedef T value_type;
	};

	template <class T>
	struct remove_pr<const T&> 
	{
		typedef T value_type;
	};

	class Any
	{
	public:
		class PlaceHolder
		{
		public:
			virtual ~PlaceHolder(){}
			virtual const std::type_info& type() const = 0;
			virtual PlaceHolder* clone() const = 0;
		};

		template<typename T>
		class Holder : public PlaceHolder
		{
		public:
			explicit Holder(const T& val)
				:value_(val)
			{
			}
			virtual const std::type_info& type() const
			{
				return typeid(T);
			}
			virtual PlaceHolder* clone() const
			{
				return new Holder(value_);
			}
		private:
			Holder & operator=(const Holder &);
		public:
			T value_;
		};


	public:
		Any()
			:content_(NULL)
		{}

		template<typename T>
		Any(const T& val)
			:content_(new Holder<T>(val))
		{
		}

		~Any()
		{
			delete content_;
		}

		template<typename T>
		Any& operator = (const T& rhs)
		{
			Any(rhs).swap(*this);
			return *this;
		}

		Any& operator=(Any rhs)
		{
			rhs.swap(*this);
			return *this;
		}

		bool empty() const
		{
			return !content_;
		}

		const std::type_info & type() const
		{
			return content_ ? content_->type() : typeid(void);
		}

	private:
		Any& swap(Any& rhs)
		{
			std::swap(content_, rhs.content_);
			return *this;
		}
	public:
		PlaceHolder* content_;
	};


	class bad_any_cast : public std::bad_cast
	{
	public:
		virtual const char* what() const throw()
		{
			return "failed conversion using any::any_cast";
		}
	};


	template<typename T>
	inline const T* any_cast(const Any* operand)
	{
		return any_cast<T>(const_cast<Any*>(operand));
	}

	template<typename T>
	T* any_cast(Any* operand)
	{
		return operand && operand->type() == typeid(T)
			? &static_cast<Any::Holder<T>*>(operand->content_)->value_: 0;
	}

	template<typename T>
	inline T any_cast(const Any& operand)
	{
		typedef typename remove_pr<T>::value_type nonref;
		return any_cast<const nonref&>(const_cast<Any&>(operand));
	}


	template<typename T>
	T any_cast(Any& operand)
	{
		typedef typename remove_pr<T>::value_type nonref;
		nonref* result = any_cast<nonref>(&operand);
		if(0==result)
		{
			throw bad_any_cast();
		}
		return *result;
	}


	// unsafe_any_cast
	template<typename T>
	inline const T * unsafe_any_cast(const Any* operand)
	{
		return unsafe_any_cast<T>(const_cast<Any *>(operand));
	}

	template<typename T>
	inline T * unsafe_any_cast(Any* operand)
	{
		return &static_cast<Any::Holder<T>*>(operand->content_)->value_;
	}

}









#endif //_f239dbe3_61ae_4e54_81bc_b829a35f6e9f__ANY_H__